home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / actlib13.zip / STRINGS.ZIP / REGEXP.C < prev    next >
C/C++ Source or Header  |  1993-04-08  |  7KB  |  285 lines

  1. /*  Copyright (C) 1993   Marc Stern  (internet: stern@mble.philips.be)  */
  2.  
  3. #include "strings.h"
  4. #include <stdlib.h>
  5.  
  6.  
  7. /*
  8.    Functions :   matchset
  9.                  match
  10.                  recursexp
  11.                  regexp
  12. */
  13.  
  14.  
  15.  
  16. /***
  17.  *  Function    :  matchset
  18.  *
  19.  *  Description :  Test if a character matches a set expression.
  20.  *
  21.  *  Parameters  :  in    char c          character to be matched
  22.  *                 in    char *pattern   regular expression to match
  23.  *
  24.  *  Parameters  :  in   char   *string
  25.  *
  26.  *  Decisions   :  The following symbols are treated specially:
  27.  *
  28.  *              \  quote next character      -  range of values
  29.  *              ^  non-inclusion (if first character)
  30.  *
  31.  *              ex: aeiou0-9   match a, e, i, o, u, and 0 thru 9
  32.  *                  ^aeiou0-9  match anything but a, e, i, o, u, and 0 thru 9
  33.  *
  34.  *  Return      :  1 or 0
  35.  *
  36.  *  OS/Compiler :  All
  37.  ***/
  38.  
  39. int matchset( char c, char *pattern )
  40.  
  41. { const char *begin;
  42.   int match_ok = 1;
  43.  
  44.   if ( ! c ) return 0;
  45.  
  46.   if ( *pattern == '^' ) { match_ok = 0; pattern ++; }
  47.  
  48.   for ( begin = pattern; *pattern; begin = pattern++ )
  49.       {
  50.         if ( (*pattern == '-') && (pattern != begin) )  /* range */
  51.            {
  52.              pattern ++; if ( *pattern == '\\' ) pattern ++;
  53.              if ( (min(*pattern, *begin) <= c) && (max(*pattern, *begin) >= c) )
  54.                 return match_ok;
  55.            }
  56.  
  57.         if ( *pattern == '\\' ) pattern++;
  58.  
  59.         if ( *pattern == c ) return match_ok;
  60.       }
  61.  
  62.   return (! match_ok);
  63. }
  64.  
  65.  
  66.  
  67.  
  68. /***
  69.  *  Function    :  match (internal)
  70.  *
  71.  *  Description :  Returns the number of character of a string matched
  72.  *                 by a one character regular expression.
  73.  *
  74.  *  Decisions   :  The following symbols are treated specially:
  75.  *
  76.  *                 .  any character             \  quote next character
  77.  *                 [] set of characters
  78.  *
  79.  *  Parameters  :  in   char *string    input string to be matched
  80.  *                 in   char *pattern   regular expression to match
  81.  *
  82.  *  Side-effects:  pattern contents will be destroyed.
  83.  *
  84.  *  Return      :  number of character matched by regular expression
  85.  *                 0 if not matched
  86.  *
  87.  *  OS/Compiler :  All
  88.  ***/
  89.  
  90. static int near match( const char *string, char *pattern )
  91.  
  92. { char *ptr;
  93.   int  length = 0;
  94.                  
  95.   switch ( *pattern )
  96.          {
  97.            case '.' : *pattern = '\0';
  98.                       length = strlen(string);
  99.                       break;
  100.  
  101.            case '[' : for ( ptr = ++pattern;
  102.                            *ptr && ! (*ptr == ']' && *(ptr - 1) != '\\');
  103.                            ptr ++ );
  104.  
  105.                       if ( *ptr ) *ptr = '\0';
  106.                       while ( matchset(*string++, pattern) ) length ++;
  107.                       break;
  108.  
  109.            case '\\': pattern ++;
  110.  
  111.            default  : while ( *string++ == *pattern ) length ++;
  112.                       *pattern = '\0';
  113.                       break;
  114.           }
  115.  
  116.   return length;
  117. }
  118.  
  119.  
  120.  
  121.  
  122. /***
  123.  *  Function    :  recursexp
  124.  *
  125.  *  Description :  Returns the number of character of a string matched
  126.  *                 by a regular expression.
  127.  *
  128.  *  Decisions   :  The following symbols are treated specially:
  129.  *
  130.  *                 .  any character             \  quote next character
  131.  *                 *  match zero or more        +  match one or more
  132.  *                 [] set of characters
  133.  *
  134.  *
  135.  *  Parameters  :  in   char *string    input string to be matched
  136.  *                 in   char *pattern   regular expression to match
  137.  *
  138.  *  Return      :  number of character matched by regular expression
  139.  *                 -1 if not matched
  140.  *
  141.  *  OS/Compiler :  All
  142.  ***/
  143.  
  144. int recursexp( const char *string, char *pattern )
  145.  
  146. { int count1, count2 = -1, minone = 0;
  147.   char *pattrn, *ptr;
  148.  
  149.   if ( ! *pattern ) return 0;
  150.  
  151.   ptr = pattrn = strdup( pattern );     /* store it for free() */
  152.   count1 = match( string, pattrn );
  153.   if ( count1 < 0 ) { free( ptr );
  154.                       return -1;
  155.                     }
  156.  
  157.   while ( *pattrn++ );
  158.  
  159.   switch ( *pattrn )
  160.          {
  161.            case '\0': free( ptr );
  162.                       if ( count1 ) return 1;
  163.                                else return -1;
  164.  
  165.            case '*': pattrn ++;
  166.                      minone = 0;
  167.                      break;
  168.  
  169.            case '+': if ( ! count1 ) { free( ptr );
  170.                                        return -1; 
  171.                                      }
  172.                      pattrn ++;
  173.                      break;
  174.  
  175.            default : if ( ! count1 ) { free( ptr );
  176.                                        return -1; 
  177.                                      }
  178.                      count1 = 1;
  179.                      break;
  180.          }
  181.  
  182.   for ( ; count1 >= 0; count1 -- )
  183.       {
  184.         count2 = recursexp( string + count1, pattrn );
  185.         if ( count2 >= 0 ) break;
  186.       }
  187.  
  188.   free( ptr );
  189.  
  190.   if ( count2 < 0 ) return -1;
  191.   if ( ! count1 && minone ) return -1;
  192.  
  193.   return (count1 + count2);
  194. }
  195.  
  196.  
  197.  
  198.  
  199. /***
  200.  *  Function    :  regexp
  201.  *
  202.  *  Description :  Returns the string matched by a regular expression
  203.  *                 into a string.
  204.  *
  205.  *  Decisions   :  The following symbols are treated specially:
  206.  *
  207.  *                 ^  start of line             $  end of line
  208.  *                 ?  any character             \  quote next character
  209.  *                 *  match zero or more        [] set of characters
  210.  *
  211.  *              ex: [aeiou0-9]   match a, e, i, o, u, and 0 thru 9
  212.  *                  [^aeiou0-9]  match anything but a, e, i, o, u, and 0 thru 9
  213.  *
  214.  *  Parameters  :  out   char *outstr    resulting string
  215.  *                 in    char *string    input string in which we search
  216.  *                 in    char *pattern   regular expression to match
  217.  *
  218.  *  Return      :  - pointer to resulting string
  219.  *                 - if ( outstr == NULL ) returns pointer to matched string
  220.  *                   inside 'string'.
  221.  *
  222.  *  OS/Compiler :  All
  223.  ***/
  224.  
  225. char *regexp( char *outstr, const char *string, const char *pattern )
  226.  
  227. { char *ptr, *pattrn;
  228.   int count, begin = 0, end = 0;
  229.  
  230.   pattrn = strdup( pattern );
  231.   ptr = strend( pattrn ) - 1;
  232.   if ( (*ptr == '$') && (*(ptr - 1) != '\\') )   /* Match end of line */
  233.      {
  234.        end = 1;
  235.        *ptr = '\0';
  236.      }
  237.  
  238.   ptr = pattrn;  /* store it for free() */
  239.  
  240.   if ( *pattrn == '^' )        /* Match begin of line */
  241.      {
  242.        begin = 1;
  243.        pattrn ++;
  244.      }
  245.  
  246.   for (; *string; string ++ )
  247.       if ( (count = recursexp(string, pattrn)) >= 0 || begin ) break;
  248.  
  249.   free( ptr );
  250.  
  251.   if ( end && (count != strlen(string)) ) count = 0;
  252.  
  253.   if ( outstr )
  254.      {
  255.        strleft( outstr, string, count );
  256.        return outstr;
  257.      }
  258.   return (char *)string;
  259. }
  260.  
  261.  
  262. #ifdef TEST
  263.  
  264. #include <stdio.h>
  265. #include <stdlib.h>
  266.  
  267. void main()
  268.  
  269. { char string[255], pattern[255], result[255];
  270.  
  271.   regexp( result, "I123", "[^A-Z\\-^][0-9]+\\.*" );
  272.   printf( "\n    Result : %s\n\n", result );
  273.   exit(1);
  274.  
  275.   for (;;) {
  276.              printf( "\n    String : " ); gets( string );
  277.              printf( "    Pattern: " ); gets( pattern );
  278.  
  279.              regexp( result, string, pattern );
  280.              printf( "\n    Result : %s\n\n", result );
  281.            }
  282. }
  283.  
  284. #endif
  285.